/*
 * Copyright (C) 2008-2011 CBDP Consortium
 * 
 * All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.
 * 
 * This software consists of contributions made by many individuals, 
 * listed below:
 *
 * Author: 	Xabier Laiseca <xabier.laiseca@deusto.es>
 * 			David Ausín <david.ausin@deusto.es>
 */
package cbdp.server.contextreasoner.internal.containers;

import java.lang.reflect.Field;

import cbdp.server.contextreasoner.configuration.model.Configuration;
import cbdp.server.contextreasoner.impl.jena.OSGiBundleLocator;
import cbdp.server.contextreasoner.internal.OntologyContainer;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.LocationMapper;

public abstract class BaseOntologyContainer implements OntologyContainer
{
	private final static String MAPPING_FILE = "/resources/configuration/mappings.n3";
	
	private OntModelSpec ontModelSpec;
	private Configuration configuration;
	private OntModel ontModel;
	
	
	protected final OntModelSpec getOntModelSpec()
	{
		if(ontModelSpec == null)
		{
			ontModelSpec = createOntModelSpec();
			
			if(ontModelSpec == null)
			{
				ontModelSpec = new OntModelSpec(OntModelSpec.OWL_MEM_MINI_RULE_INF);
			}
			
			addFileManagerToOntModelSpec();
		}
		
		return ontModelSpec;
	}
	
	private OntModelSpec createOntModelSpec()
	{
		if ((configuration.getOntologySpecAttributeName() != null) && (configuration.getOntologySpecClassName() != null))
		{
			try
			{
				final Class<?> specClass = Class.forName(configuration.getOntologySpecClassName());
				final Field specField = specClass.getDeclaredField(configuration.getOntologySpecAttributeName());
				return (OntModelSpec) specField.get(null);
			}
			catch (final ClassNotFoundException e)
			{
				System.out.println("Ontology specification class not found.");
				e.printStackTrace();
				return null;
			}
			catch (SecurityException e)
			{
				System.out.println("The attribute is not accessible.");
				e.printStackTrace();
				return null;
			}
			catch (NoSuchFieldException e)
			{
				System.out.println("The attribute does not exists.");
				e.printStackTrace();
				return null;
			}
			catch (IllegalArgumentException e)
			{
				System.out.println("The attribute is not static.");
				e.printStackTrace();
				return null;
			} 
			catch (IllegalAccessException e)
			{
				System.out.println("The attribute is not accessible.");
				e.printStackTrace();
				return null;
			}
			catch(ClassCastException e)
			{
				System.out.println("The attribute is not a ontology model specification.");
				e.printStackTrace();
				return null;
			}
		}
		
		return null;
	}
	
	@Override
	public final void setOntModelSpec(final OntModelSpec ontModelSpec)
	{
		this.ontModelSpec = ontModelSpec;
		
		addFileManagerToOntModelSpec();
	}

	protected final Configuration getConfiguration()
	{
		return configuration;
	}
	
	@Override
	public final void setConfiguration(final Configuration configuration)
	{
		this.configuration = configuration;
	}

	@Override
	public final OntModel getOntModel()
	{
		return ontModel;
	}
	
	protected final void setOntModel(final OntModel ontModel)
	{
		this.ontModel = ontModel;
	}
	
	private void addFileManagerToOntModelSpec()
	{
		final FileManager fileManager = createFileManager();
		ontModelSpec.getDocumentManager().setFileManager(fileManager);
	}
	
	private FileManager createFileManager()
	{
		final String mappingFile = (getConfiguration().getMappingFileLocation() != null)?
				getConfiguration().getMappingFileLocation():
				MAPPING_FILE;
		
		final LocationMapper locationMapper = new LocationMapper(mappingFile);
		
		final FileManager fileManager = new FileManager(locationMapper);
		fileManager.addLocator(new OSGiBundleLocator());
		fileManager.addLocatorFile();
		fileManager.addLocatorURL();
		
		return fileManager;
	}
}
